iT邦幫忙

2024 iThome 鐵人賽

DAY 17
0
自我挑戰組

上班辦公室,下班讀書室:RISC-V / ARM64 體系結構編程與實踐系列 第 17

[鐵人賽] Day 17 ARM 第 5 章節 A64指令集(3) -- Compare & Branch Instruction

  • 分享至 

  • xImage
  •  

今日的行程:

讀書室:17:00 - 18:00

正片開始

Compare

// 常用的 suffix
eq:    相等 (Z == 1)
ne:    不相等 (Z == 0)
cs/hs: 無號數溢位 (C == 1)
cc/lo: 沒有無號數溢位 (C == 0)
mi:    負數 (N == 1)
pl:    非負數 (N == 0)
vs:    溢位 (V == 1)
vc:    未溢位 (V == 0)

// CMP:  是用 SUBS 來實作的,會影響到 nzcv
cmp x1, x2        // subs xzr, x1, x2 ==> x1 + not(x2) + 1
b.cs label        // if C bit is set, then branch to label

// CMN: 是用 ADDS 來實作的,用來比較一個數與另一個數的相反數
    mov x1, #2
    mov x2, #-2
1:
    cmn x1, x2    // adds xzr, x1, x2 ==> x1 + x2
    b.eq 1b       // Z bit set, so branch to "1"
    
// CSEL, CSET, CSINC
CSEL <Xd>, <Xn>, <Xm>, <cond>    // if (cond) ? (Xd = Xn) : (Xd = Xm)

ex.
unsigned long csel_test (unsigned long a, unsigned long b)
{
    if (a >= b)
        return b + 2;
    else
        return b - 1;
}
可以寫成
cmp x0, x1        // x0 == a, x1 == b
add x2, x1, #2
sub X3, x1, #1
csel x0, x2, x3, ge

CSET <Xd>, <cond>                // if (cond) ? (Xd = 1) : (Xd = 0)
CSINC <Xd>, <Xn>, <Xm>, <cond>   // if (cond) ? (Xd = Xn): (Xd = Xm + 1)

// B, B.cond, BL, BR, BLR
B <label>                     // 限制: PC +- 128 MB 範圍內
B.cond <label>                // 限制: PC +- 1 MB 範圍內
BL <label>                    // branch and link: 會做 "LR(X30) = PC + 4"
BR <Xn>                       // branch 到 register 儲存的 address
BRL <Xn>                      // branch 到 register 儲存的 address, LR = PC + 4

// RET, ERET
RET                           // 跳到 LR register 儲存的位址
ERET                          // 從當前的 Exception Level 返回,用在 EL 的切換

// CBZ, CBNZ, TBZ, TBNZ
CBZ <Xt>, <label>             // if (Xt == 0) then b label; (PC +- 1MB)
CBNZ <Xt>, <label>            // if (Xt != 0) then b label; (PC +- 1MB)
TBZ R<t>, #imm, label         // if (R[imm bit] == 0) then branch label; (PC +- 32KB)
TBNZ R<t>, #imm, label        // if (R[imm bit] != 0) then branch label; (PC +- 32KB)

常見錯誤

.global csel_test
    cmp x0, 0
    add x2, x1, 1
    sub X3, x1, 2
    csel x0, x3, x2, eq
    ret

.global bl_test:
    mov x0, 1
    mov x1, 3
    bl csel_test
    ret

若有 function (A) 呼叫 bl_test,那麼會在 bl_test return 的時候,進入無限循環。
因為 bl 會修改 LR register 導致,bl_test return 回 A 的時候,跳到不預期的位址 (bl_test 的位址)

解決方法就是,進到一個 function 之後,會先把這個 function 的 LR 存到 stack 上
(function prologue 通常都會做這件事情)

總結

  • RISC-V 提供的 branch 指令有兩種: JAL, JALR (都會把 PC + 4 存回 rd)
    • JAL rd, address: e.g. jal ra, 0x1234 (address 限制是 PC +- 1MB)
    • JALR rd, offset(rs1): e.g. jalr ra, 0x8(a1) (offset 限制是 -2048~2047)
    • 並且提供了多種的 pseudo instruction
      • j label: jal x0, label
      • jal label: jal ra, label
      • jr rs: jalr x0, 0(rs)
      • jalr rs: jalr ra, 0(rs)
      • ret: jalr x0, 0(ra)
      • call func: auipc ra, offset[31:12] + offset[11]; jalr ra, offset[11:0](ra)
      • tail func: auipc x6, offset[31:12] + offset[11]; jalr ra, offset[11:0](x6)

上一篇
[鐵人賽] Day 16 ARM 第 4 章節 A64指令集(2) -- Arithmetic & Shifting Instruction
下一篇
[鐵人賽] Day 18 ARM 第 6 章節 A64指令集(4) -- Other Important Instructions
系列文
上班辦公室,下班讀書室:RISC-V / ARM64 體系結構編程與實踐30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言